//
// Created by lenovo on 2024/7/2.
//

#ifndef TEYVATSURVIVAL_GAME_GAME_H
#define TEYVATSURVIVAL_GAME_GAME_H
#include "./Obj/GameObj.h"
#include "./Msg/Message.h"
#include "./weapon/Weapon.h"
#include <vector>
namespace Game{
    class GAME{
    public:
        Obj::Player* player ;
        std::vector<Obj::Bullet*> bullets ;
        std::vector<Obj::Enemy*> enemys ;
        Msg::MsgBus& eBus = Msg::MsgBus::getInstance();
        Obj::Wea::BulletOrbitWeapon* weapon;
        bool _over {false};
        bool _show_collider {false};

        GAME(){
//            cManager = Obj::CollisionManager::getInstance();
            player = new Obj::Player ;
            player->setPosition({500,350});
            for (int i = 0 ; i < 5 ; i ++){
                enemys.push_back(new Obj::Enemy(player));
            }
            enemys[0]->setPosition(Vector2f({10,10}));
            enemys[1]->setPosition(Vector2f({500,600}));
            enemys[2]->setPosition(Vector2f({30,120}));
            enemys[3]->setPosition(Vector2f({90,60}));
            enemys[4]->setPosition(Vector2f({300,360}));

            weapon = new Obj::Wea::BulletOrbitWeapon(player);
            for (auto b : weapon->bullets){
                bullets.push_back(b);
            }
        }

        void update(float delta){
            if (not player){
                cout << "Game Over" << endl ;
                _over = true ;
                return ;
            }

            handleDestroyEvents();

            player->update(delta);
            for (auto enemy : enemys){
                enemy->update(delta);
            }

            weapon->update(delta);

            checkCollision();
            handleCollisionEvents();
            handleDestroyEvents();
        }

        void draw(sf::RenderWindow& window){
            for (auto b : bullets){
                b->draw(window);
            }
            for (auto e : enemys){
                e->draw(window);
            }
            if (player)
                player->draw(window);
            if (_show_collider){
                drawCollider(window);
            }
        }



        void checkCollision(){
//            cout << "checkCollision" << endl ;
            if (player == nullptr)
                return ;
            for (auto enemy : enemys){
                if (enemy == nullptr)
                    continue;
                if (enemy->collider->intersect(*player->collider)){
#ifdef DEBUG_MSG
                    cout << "collided" << endl ;
#endif
                    eBus.post(
                            new Msg::CollisionMsg(
                                    enemy, player
                                    )
                            );
                }
            }

            // 敌人之间的碰撞检测
            for (size_t i = 0; i < enemys.size(); ++i) {
                for (size_t j = i + 1; j < enemys.size(); ++j) {
                    if (enemys[i]->collider && enemys[j]->collider && enemys[i]->collider->intersect(*enemys[j]->collider)) {
                        // 处理敌人之间的碰撞
#ifdef DEBUG_MSG
                        cout << "collided" << endl ;
#endif
                        eBus.post(
                                new Msg::CollisionMsg(
                                        enemys[i],enemys[j]
                                )
                        );

                    }
                }
            }

            //bullets 与 enemy之间的碰撞
            for (auto bullet : bullets) {
               for (auto enemy : enemys){
                   if (enemy->collider and bullet->collider and enemy->collider->intersect(*bullet->collider)){
                       eBus.post(
                               new Msg::CollisionMsg(
                                       enemy, bullet
                               )
                       );
                   }

               }
            }
        }

        void handleDestroyEvents() {
//            cout << "handleEvents" << endl;
            using namespace Game::Msg;

#ifdef DEBUG_MSG
            //计数逻辑，看是否有东西被删掉了
            auto objs1 =
                    (player ? 1 : 0 ) +
                    bullets.size() +
                    enemys.size() ;
#endif

            // 处理销毁事件
            for (auto event: eBus.getMsgs(Message::Type::Destroy)) {
                GameObj *obj = event->getSender();
                destroyObj(obj);
                delete event; // 记得删除事件以防止内存泄漏
            }

#ifdef DEBUG_MSG
            //查看是否删除成功
            auto objs2 =
                    (player ? 1 : 0 ) +
                    bullets.size() +
                    enemys.size() ;
            if (objs1 > objs2){
                cout << "remove " << objs1 - objs2 << " targets " << endl ;
            }
#endif
        }

        void handleCollisionEvents(){
            using namespace Game::Msg;
            auto& cMsgs = eBus.getMsgs(Message::Type::Collision);
//            cout << "CollisionEvents : " << cMsgs.size() << endl;

            // 碰撞事件处理
            for (auto msg : cMsgs) {

                // 游戏逻辑层面的处理
                auto* cMsg = dynamic_cast<CollisionMsg*>(msg);
                if (cMsg) {
#ifdef DEBUG_MSG
                    cout << "get One collision msg to be handel" << endl ;
#endif

                    auto [c1, c2] = cMsg->getCollidePair();
                    c1->onCollision(c2);
                    c2->onCollision(c1);

                    eBus.removeMsg(msg);
                }
            }


        }

        void destroyObj(Obj::GameObj* obj) {
            if (obj == player) {
                delete player;
                player = nullptr;
                eBus.removeByObj(obj);
#ifdef DEBUG_MSG
                if (player);
                else{
                    cout << "player destroyed" << endl ;
                }
#endif
                return ;
            }

            auto db = std::remove(bullets.begin(), bullets.end(), obj);
            if (db != bullets.end()) {
                 bullets.erase(db);
                 delete obj;
                 eBus.removeByObj(obj);
            }

            auto de = std::remove(enemys.begin(), enemys.end(), obj);
            if (de != enemys.end()) {
                enemys.erase(de);
                delete obj;
                eBus.removeByObj(obj);
            }
        }


        void drawCollider(sf::RenderWindow& window){
            if (player)
                Phy::Collision::drawCollider(window , *player->collider);
            for (auto b : bullets){
                if (b->collider){
                    Phy::Collision::drawCollider(window , *b->collider);
                }
            }
            for (auto e : enemys){
                if (e->collider){
                    Phy::Collision::drawCollider(window , *e->collider);
                }
            }
        }

        void over(){
            _over = true ;
        }
    };
}
#endif //TEYVATSURVIVAL_GAME_GAME_H
